﻿using NCS.IConnect.Core.WebApi.Properties;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.IConnect.Core.Utilities;
using System.Collections;
using System.Web.Http.ModelBinding;

namespace NCS.IConnect.Core.WebApi.Description
{
    /// <summary>
    /// The request/response content specific descriptor.
    /// </summary>
    public class HttpContentDescriptor
    {
        /// <summary>
        /// Gets the type of the content data.
        /// </summary>
        /// <value>The type of the content data.</value>
        public Type DataType { get; private set; }

        /// <summary>
        /// Gets the supported media types.
        /// </summary>
        /// <value>The supported media types.</value>
        public string[] SupportedMediaTypes { get; private set; }

        /// <summary>
        /// Gets the sample.
        /// </summary>
        /// <value>The sample.</value>
        public object Sample { get; private set; }

        /// <summary>
        /// Gets the error code.
        /// </summary>
        /// <value>The error code.</value>
        public string ErrorCode { get; private set; }

        /// <summary>
        /// Gets a value indicating whether this instance is error content.
        /// </summary>
        /// <value><c>true</c> if this instance is error content; otherwise, <c>false</c>.</value>
        public bool IsErrorContent
        {
            get { return !string.IsNullOrEmpty(this.ErrorCode); }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="HttpContentDescriptor"/> class.
        /// </summary>
        /// <param name="dataType">Type of the data.</param>
        /// <param name="sampleAccessor">The sample accessor.</param>
        /// <param name="supportedMediaTypes">The supported media types.</param>
        public HttpContentDescriptor(Type dataType, Func<Type, object> sampleAccessor, string[] supportedMediaTypes = null)
        {
            Guard.ArgumentNotNull(dataType, "dataType");
            Guard.ArgumentNotNull(sampleAccessor, "sampleAccessor");

            this.DataType = dataType;
            this.SupportedMediaTypes = supportedMediaTypes ?? new string[] { @"application/json", @"application/xml", @"application/x-www-form-urlencoded" };
            if (this.SupportedMediaTypes.Contains(@"application/x-www-form-urlencoded"))
            {
                if (!new JQueryMvcFormUrlEncodedFormatter().CanReadType(dataType))
                {
                    List<string> all = new List<string>(this.SupportedMediaTypes);
                    all.Remove(@"application/x-www-form-urlencoded");
                    this.SupportedMediaTypes = all.ToArray();
                }
            }
            this.Sample = sampleAccessor(this.DataType);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="HttpContentDescriptor"/> class.
        /// </summary>
        /// <param name="errorCode">The error code.</param>
        /// <param name="supportedMediaTypes">The supported media types.</param>
        /// <exception cref="System.ArgumentException">If specified error code is invalid.</exception>
        public HttpContentDescriptor(string errorCode,  string[] supportedMediaTypes = null)
        {
            Guard.ArgumentNotNullOrEmpty(errorCode, "errorCode");
            this.ErrorCode = errorCode;
            this.DataType = typeof(ErrorInfo);
            ErrorInfo error;
            if (!Errors.TryGetError(errorCode, out error))
            { 
                throw new ArgumentException(errorCode, Resources.ExceptionErrorNotFound.Format(new object[]{errorCode}));
            }
            this.Sample = error;
            this.SupportedMediaTypes = supportedMediaTypes ?? new string[] { @"application/json", @"application/xml" };
        }
    }
}